#include "heaptimer.h"

size_t HeapTimer::size() {
    return container_.size() - 1;
}

bool HeapTimer::empty() {
    return !size();
}

TimerNode HeapTimer::top() {
    assert(size());
    return container_[1];
}

void HeapTimer::pop() {
    swap(1, size());
    LOG_DEBUG("pop sock: [%d]", container_.back());
    container_.back().callback();
    ref_.erase(container_.back().sock_fd);
    container_.pop_back();
    if (size()) down(1, size());
}

void HeapTimer::clear() {
    ref_.clear();
    container_.clear();
}

void HeapTimer::push(int sock_fd, int time_out, const TimeoutCallBack& callback) {
    if (ref_.count(sock_fd)) {
        update(sock_fd, time_out);
        LOG_DEBUG("更新socket: %d, container size: %d 对应结点编号: %d", sock_fd, size(), ref_[sock_fd]);

    } else {
        TimerNode node;
        node.sock_fd = sock_fd;
        node.expires = Clock::now() + MS(time_out);
        node.callback = callback;
        container_.emplace_back(node);
        ref_[sock_fd] = size();
        up(size());
        LOG_DEBUG("加入socket%d, container size:%d 对应结点编号:%d", sock_fd, size(), ref_[sock_fd]);
    }
}

void HeapTimer::update(int sock_fd, int new_expires) {
    assert(ref_.count(sock_fd));
    container_[ref_[sock_fd]].expires = Clock::now() + MS(new_expires);
    down(ref_[sock_fd], size());
}

void HeapTimer::delFd(int id) {
    LOG_DEBUG("delFD");
    if (ref_.count(id)) del(ref_[id]);
}


int HeapTimer::GetNextTick() {
    tick();
    int res = -1;
    if(size()) {
        res = std::chrono::duration_cast<MS>(top().expires - Clock::now()).count();
        if(res < 0) res = 0; 
    }
    return res;

}


void HeapTimer::swap(size_t i, size_t j) {
    std::swap(container_[i], container_[j]);
    ref_[container_[i].sock_fd] = j;
    ref_[container_[j].sock_fd] = i;
}
    
void HeapTimer::up(size_t i) {  
    while (i > 1 && container_[i / 2] < container_[i]) {
        swap(i / 2, i);
        i /= 2;
    }
}

void HeapTimer::down(size_t i, size_t n) {
    while ((i * 2 <= n && container_[i * 2] < container_[i]) || (i * 2 + 1 <= n && container_[i * 2 + 1] < container_[i])) {
        size_t l = i * 2, r = i * 2 + 1;
        if (r > n || container_[l] < container_[r]) {
            swap(i, l);
            r = l;
        } 
        else {
            swap(i, r);
            i = r;
        }
    }
}

void HeapTimer::del(size_t i) {
    assert(i > 0 && i <= size());

    LOG_DEBUG("删除结点:%d, 对应sock_fd:%d", i, container_[i].sock_fd);

    swap(i, size());
    ref_.erase(container_.back().sock_fd);
    container_.back().callback();
    container_.pop_back();
    if (i > 0 && i <= size()) {
        up(i);
        down(i, size());
    } 
}



void HeapTimer::tick() {
    while (size()) {
        auto node = top();
        if (std::chrono::duration_cast<MS> (node.expires - Clock::now()).count() > 0) break;
        pop();
    }
}
